package com.feshfans.controller;

import com.feshfans.controller.eventhandler.MultiContollerEventHandler;
import com.feshfans.controller.eventhandler.SingleControllerEventHandler;
import com.feshfans.po.ControllerEntity;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.EntityBareJid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.plaf.nimbus.State;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 管理各窗口
 */
public class StageManager {

    private static final Logger Log = LoggerFactory.getLogger(StageManager.class);

    private static final Map<BareJid, Stage> messageStageMap = new HashMap<>();
    private static final Map<BareJid, Stage> roomStageMap = new HashMap<>();
    private static Stage loginStage;
    private static Stage mainStage;
    private static Stage tempMessageStage;
    private static Stage addRoomStage;


    public static Stage openOrGetLoginStage() throws IOException {
        if(loginStage==null){
            ControllerEntity<Void> controllerEntity = new ControllerEntity<>("/fxml/Login.fxml","MyIM Login",300,350);
            Stage primaryStage = load(controllerEntity);
            controllerEntity.setOnCloseRequestEventHandler(new SingleControllerEventHandler(primaryStage,null));
            addEventHandler(primaryStage,controllerEntity);
            loginStage = primaryStage;
            return primaryStage;
        } else {
            return loginStage;
        }
    }

    public static Stage openOrGetMainStage(){
        //显示主窗口
        if(mainStage == null){
            ControllerEntity<Void> controllerEntity = new ControllerEntity<>("/fxml/Main.fxml","MyIM",300,600);
            Stage stage = load(controllerEntity);
            controllerEntity.setOnCloseRequestEventHandler(new SingleControllerEventHandler(stage,null));
            addEventHandler(stage,controllerEntity);
            mainStage = stage;
            return stage;
        } else {
            return mainStage;
        }
    }

    public static Stage openOrGetTempMessageStage(){
        if(tempMessageStage == null){
            ControllerEntity<Void> controllerEntity = new ControllerEntity<>("/fxml/TempMessage.fxml","发送临时消息",400,500);
            Stage stage = load(controllerEntity);
            controllerEntity.setOnCloseRequestEventHandler(new SingleControllerEventHandler(stage,null));
            addEventHandler(stage,controllerEntity);
            tempMessageStage = stage;
            return stage;
        } else {
            return tempMessageStage;
        }
    }

    public static Stage openOrGetAddRoomStage(){
        if(addRoomStage == null){
            ControllerEntity<Void> controllerEntity = new ControllerEntity<>("/fxml/AddRoom.fxml","添加房间",300,300);
            Stage stage = load(controllerEntity);
            controllerEntity.setOnCloseRequestEventHandler(new SingleControllerEventHandler(stage,null));
            addEventHandler(stage,controllerEntity);
            addRoomStage = stage;
            return stage;
        } else {
            return addRoomStage;
        }
    }

    public static void openOrGetRoomStage(EntityBareJid jid){
        Stage stage;
        if(roomStageMap.containsKey(jid)){

        } else {
            ControllerEntity<BareJid> controllerEntity = new ControllerEntity<>("/fxml/Room.fxml",jid.toString() ,600,600);
            controllerEntity.setT(jid);
            stage= load(controllerEntity);

            roomStageMap.put(jid,stage);
            controllerEntity.setOnCloseRequestEventHandler(new MultiContollerEventHandler(roomStageMap,jid));
            addEventHandler(stage,controllerEntity);
        }
    }

    public static void openOrGetMessageStage(BareJid jid){
        Stage stage;
        if(messageStageMap.containsKey(jid)){

        } else {
            ControllerEntity<BareJid> controllerEntity = new ControllerEntity<>("/fxml/Message.fxml",jid.toString() ,600,600);
            controllerEntity.setT(jid);

            stage= load(controllerEntity);
            messageStageMap.put(jid,stage);

            // 设置监听事件，关闭时从缓存中删除
            controllerEntity.setOnCloseRequestEventHandler(new MultiContollerEventHandler(messageStageMap,jid));

            addEventHandler(stage,controllerEntity);
        }
    }

    private static<T> void addEventHandler(Stage stage, ControllerEntity<T> controllerEntity){
        if(controllerEntity.getOnCloseRequestEventHandler()!=null){
            stage.setOnCloseRequest(controllerEntity.getOnCloseRequestEventHandler());
        }
    }

    private static <T> Stage load(ControllerEntity<T> controllerEntity){
        try {
            // 一定要用下面这种写法，否则 getController() 返回 null.
            // FXMLLoader fxmlLoader = new FXMLLoader();
            // fxmlLoader.load(StageManager.class.getResource(controllerEntity.getFxmlPath()))
            // 上面这种写法就不行，个人觉得这是 FXMLLoader 的一个 bug
            FXMLLoader fxmlLoader = new FXMLLoader(StageManager.class.getResource(controllerEntity.getFxmlPath()));
            Parent root = fxmlLoader.load();
            // 获取 controller 执行 onLoad 函数
            Controller controller = fxmlLoader.getController();

            controller.onLoad(controllerEntity.getT());

            // 如果是可注册的，执行注册函数
            if(controller instanceof RegisteredController){
                ((RegisteredController) controller).register();
            }

            Stage stage = new Stage();
            stage.setTitle(controllerEntity.getTitle());
            stage.setScene(new Scene(root, controllerEntity.getWidth(), controllerEntity.getHeight()));

            //addEventHandler(stage,controllerEntity);

            // 将 controller 放到 stage 中，方便在关闭窗口时使用
            stage.setUserData(controller);
            stage.show();
            return stage;

        } catch (IOException e) {
            Log.error("加载 FXML 出错:{}",controllerEntity.getFxmlPath(),e);
            return null;
        }

    }
}
